package GUI.view;

import java.awt.GridLayout;
import java.awt.Toolkit;
import java.util.Properties;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;

import GUI.models.TreeNodeImplProperties;

import client.domainModels.Node.Node;
import client.domainModels.NodeImpl.AbstractNode;
import client.domainModels.NodeImpl.LogFile;

/**
 * 
 * @author Wei WANG
 */

public class XMLFileTree extends JPanel {
	protected TreeNodeImplProperties rootNode;
	protected DefaultTreeModel treeModel;
	protected JTree tree;
	private Toolkit toolkit = Toolkit.getDefaultToolkit();
	private LogFile rootcase;

	public XMLFileTree() {
		super(new GridLayout(1, 0));

		rootcase = new LogFile();
		rootcase.setID("LogFile");
		rootNode = new TreeNodeImplProperties(rootcase);
		treeModel = new DefaultTreeModel(rootNode);
		treeModel.addTreeModelListener(new MyTreeModelListener());
		tree = new JTree(treeModel);
		tree.setEditable(false);
		tree.getSelectionModel().setSelectionMode(
				TreeSelectionModel.SINGLE_TREE_SELECTION);
		tree.setShowsRootHandles(true);

		JScrollPane scrollPane = new JScrollPane(tree);
		add(scrollPane);
	}

	/** Remove all nodes except the root node. */
	public void clear() {
		getRootNode().removeAllChildren();
		rootNode.removeAllChildren();
		treeModel.reload();
	}

	public LogFile getRootNode() {
		return rootcase;
	}

	/** Remove the currently selected node. */
	public void removeCurrentNode() {
		TreePath currentSelection = tree.getSelectionPath();
		if (currentSelection != null) {
			TreeNodeImplProperties currentNode = (TreeNodeImplProperties) (currentSelection
					.getLastPathComponent());
			
			TreeNodeImplProperties parent = (TreeNodeImplProperties) (currentNode.getParent());
			
			AbstractNode node_current = currentNode.getPropretiesObj();
			AbstractNode parentNode = parent.getPropretiesObj();
			if (parent != null) {
				treeModel.removeNodeFromParent(currentNode);
				parentNode.removeChildNode(node_current);
				return;
			}
		}

		// Either there was no selection, or the root was selected.
		toolkit.beep();
	}
	
	public void removeCurrentNodeChildren() {
		TreePath currentSelection = tree.getSelectionPath();
		if (currentSelection != null) {
			TreeNodeImplProperties currentNode = (TreeNodeImplProperties) (currentSelection
					.getLastPathComponent());
			int childrenNumber = currentNode.getChildCount();
			Node node_current = currentNode.getPropretiesObj();
			
			if (node_current != null) {
				for(int i=0;i<childrenNumber;i++){
					treeModel.removeNodeFromParent((MutableTreeNode) currentNode.getChildAt(i));
					//node_current.removeChildNode( ((TreeNodeImplProperties) currentNode.getChildAt(i)).getPropretiesObj());
				}
				node_current.removeAllChildren();
				return;
			}
		}

		// Either there was no selection, or the root was selected.
		toolkit.beep();
	}

	public TreeNodeImplProperties getLastNode() {
		TreeNodeImplProperties parentNode = null;
		TreePath parentPath = tree.getSelectionPath();

		if (parentPath == null) {
			parentNode = rootNode;
		} else {
			parentNode = (TreeNodeImplProperties) (parentPath
					.getLastPathComponent());
		}

		return parentNode;
	}
	
	

	/** Add child to the currently selected node. */
	public TreeNodeImplProperties addObject(AbstractNode child) {
		TreeNodeImplProperties parentNode = null;
		TreePath parentPath = tree.getSelectionPath();

		if (parentPath == null) {
			parentNode = rootNode;
		} else {
			parentNode = (TreeNodeImplProperties) (parentPath
					.getLastPathComponent());
		}

		return addObject(parentNode, child, true);
	}

	public TreeNodeImplProperties addObject(TreeNodeImplProperties parent,
			AbstractNode child) {
		return addObject(parent, child, false);
	}

	public TreeNodeImplProperties addObject(TreeNodeImplProperties parent,
			AbstractNode child, boolean shouldBeVisible) {
		AbstractNode parentNode;
		TreeNodeImplProperties childNode = new TreeNodeImplProperties(
				(AbstractNode) child);

		if (parent == null) {
			parent = rootNode;
			parentNode = rootcase;
		}else{
			parentNode = parent.getPropretiesObj();
		}

		parentNode.addChildNode(child);
		// It is key to invoke this on the TreeModel, and NOT
		// TreeNodeImplProperties
		treeModel.insertNodeInto(childNode, parent, parent.getChildCount());

		// Make sure the user can see the lovely new node.
		if (shouldBeVisible) {
			tree.scrollPathToVisible(new TreePath(childNode.getPath()));
		}
		return childNode;
	}

	class MyTreeModelListener implements TreeModelListener {
		public void treeNodesChanged(TreeModelEvent e) {
			TreeNodeImplProperties node;
			node = (TreeNodeImplProperties) (e.getTreePath()
					.getLastPathComponent());

			/*
			 * If the event lists children, then the changed node is the child
			 * of the node we've already gotten. Otherwise, the changed node and
			 * the specified node are the same.
			 */

			int index = e.getChildIndices()[0];
			node = (TreeNodeImplProperties) (node.getChildAt(index));

			System.out.println("The user has finished editing the node.");
			System.out.println("New value: " + node.getUserObject());
		}

		public void treeNodesInserted(TreeModelEvent e) {
		}

		public void treeNodesRemoved(TreeModelEvent e) {
		}

		public void treeStructureChanged(TreeModelEvent e) {
		}
	}
}
